#include "dict_priv.h"
#include <strutl.h>

static void handle_utf8(unsigned char *utf8, int utf8_len, 
			unsigned char *gbk,int gbk_max_len);

static void handle_utf8(unsigned char *utf8, int utf8_len, 
			unsigned char *gbk, int gbk_max_len)
{
	utf82gbk(utf8, gbk, gbk_max_len);
	return;
}

int get_word_meaning_in_dict(apple_dict_t *dict, const char *word, 
			uint32_t index, char *output_buf)
{
	int word_len, res;
	unsigned char buf[1024], gbk[1024], temp[1024];
	int i, idx, has_zero = 0;
	char *p;

	word_len = dict->idxbuff[index + 1] - dict->idxbuff[index];
	/* printf("explain len %d, \n", word_len); */
	
	if (word_len > 1024) {
		printf("Too long this word. I cannot eat it.\n");
		return -1;
	}

	memset(gbk, 0, 1024);
	memset(buf, 0, 1024);

	lseek(dict->fd_dict, dict->idxbuff[index], SEEK_SET);
	res = read(dict->fd_dict, buf, word_len);
	if (res == -1) {
		printf("read err\n");
		return -1;
	}
	/* TODO: sametypesequence options. */
	p = output_buf;
	if (dict->stq == 1) {
		printf("[%s]\n%s: ", dict->name, word);
		memset(temp, 0, 1024);
		/* one utf8 string with '\0'. 
		 * ont utf8 string without '\0'.
		 * TODO: the first string is pronunce. 
		 * But I cannot output that correctly.
		 */
		i = idx = 0;
		while (1 && has_zero != 2) {
			temp[i++] = buf[idx++];
			if (temp[i - 1] == '\0') {
				has_zero++;
				handle_utf8(temp, word_len, gbk, 1024);
				if (has_zero == 1) {
					if (gbk[0] != '\0') {
						strcpy(p++, "[");
						strncpy(p, temp, i - 1);
						p += i - 1;
						strcpy(p, "]\n");
						p += 2;
						printf("[%s]\n", gbk);
						word_len += 3;	/* []\n */
					
					}
				} else {
					printf("%s\n", gbk);
					/* FIXME: temp is whole words. */
					strncpy(p, temp, i - 1);
					p += i - 1;
				}
				i = 0;
			}
		}
	}
	return word_len;
}

uint32_t find_word_in_idxfile(apple_dict_t *dict, const char *word)
{
	int len, res;
	uint8_t *p, *buffer = NULL;
	uint32_t index = -1;
	
	if (!dict)
		return -1;

	/* TOOD: divide into small piece. 
	 * dict->idx_size is too ...
	 */
	buffer = malloc(sizeof (uint8_t) * dict->idx_size);
	if (!buffer) {
		printf("Out of memery.\n");
		goto err;
	}
	/* go to first place */
	lseek(dict->fd_idx, 0L, SEEK_SET);
	res = read(dict->fd_idx, buffer, (sizeof (uint8_t) * dict->idx_size));
	if (res == -1)
		goto err;
	p = buffer;

	/* In idx file, every lookup word end with '\0'. 
	 * So we can use strlen to get word's length. 
	 * Next word's offset is 2 * long */
	for (index = 0; index < dict->words_count; index++) {
		len = strlen(p);
		if (strcasecmp(p, word) == 0) {
			goto find_out;
		}
		/* '\0' + offset + size */
		p += (len + 1 + 8);
		if ((uint32_t)(p - buffer) >= (dict->idx_size))
			break;
	}
err:
	index = -1;
find_out:
	if (buffer)
		free(buffer);
	return index;
}

uint32_t get_word_by_idx(apple_dict_t *dict, uint32_t idx, char *outbuf)
{
	int len, res;
	uint8_t *p, *buffer = NULL;
	uint32_t index = -1;
	
	if (!dict)
		return -1;

	/* TOOD: divide into small piece. 
	 * dict->idx_size is too ...
	 */
	buffer = malloc(sizeof (uint8_t) * dict->idx_size);
	if (!buffer) {
		printf("Out of memery.\n");
		goto err;
	}
	/* go to first place */
	lseek(dict->fd_idx, 0L, SEEK_SET);
	res = read(dict->fd_idx, buffer, (sizeof (uint8_t) * dict->idx_size));
	if (res == -1)
		goto err;
	p = buffer;

	/* In idx file, every lookup word end with '\0'. 
	 * So we can use strlen to get word's length. 
	 * Next word's offset is 2 * long */
	for (index = 0; index < dict->words_count; index++) {
		if (idx == index) {
			strcpy(outbuf, p);
			len = res = strlen(p);
			goto find_out;
		} else {
			len = strlen(p);
			/* '\0' + offset + size */
			p += (len + 1 + 8);
			if ((uint32_t)(p - buffer) >= (dict->idx_size))
				break;
		}
	}
err:
	index = -1;
find_out:
	if (buffer)
		free(buffer);
	return res;
}
/* 
 * Read *.ifo file and get total word count and idx file size.
 * Note that, ifo file is ASCII.
 */
int parse_ifo_file(apple_dict_t *dict)
{
	int res;
	char buf[STROP_MAX_BUF_LEN];

	if (!dict)
		return -1;
	/* go to first place */
	lseek(dict->fd_ifo, 0L, SEEK_SET);
	/* ifo file has '\n' */
	do {
		res = file_get_line(dict->fd_ifo, buf);
		if (res == -1)
			goto out;
		if (strncmp(buf, "wordcount=", 10) == 0) 
			dict->words_count = atol(buf + 10);
		else if (strncmp(buf, "idxfilesize=", 12) == 0) 
			dict->idx_size = atol(buf + 12);
		else if (strncmp(buf, "sametypesequence=", 17) == 0)
			dict->stq = 1;
	} while(!(dict->words_count != 0 && 
		  dict->idx_size != 0 && 
		  dict->stq != 0));
out:
	return res;
}

/* word end of '\0' */
int parse_idx_file(apple_dict_t *dict)
{
	int res;
	char ch;
	uint32_t offset, idx;
	unsigned char offset_str[4];

	idx = 0;
	
	if (!dict)
		return -1;
	/* go to first place */
	lseek(dict->fd_idx, 0L, SEEK_SET);
	for (idx = 0; idx < dict->words_count; ) {
		res = read(dict->fd_idx, &ch, 1);
		if (res == -1)
			goto out;
		if (ch != '\0')
			continue;
		idx++;
		res = read(dict->fd_idx, offset_str, sizeof (offset_str));

		offset = offset_str[0] << 24 | 
			 offset_str[1] << 16 |
			 offset_str[2] << 8 |
			 offset_str[3];

		lseek(dict->fd_idx, 4, SEEK_CUR);
		dict->idxbuff[idx-1] = offset;
	}
out:
	if (idx != dict->words_count)
		printf("parse idx file has something err, idx = %ld\n", idx);

	return res;
}

#ifdef WIN32
#define SEP	"\\"
#define OPEN_FILE_MODE_R	(O_RDONLY | O_BINARY)
#else
#define SEP	"\"
#define OPEN_FILE_MODE_R	(O_RDONLY)
#endif
int open_dict_files(apple_dict_t *dict)
{
	char ifoname[100], idxname[100], dictname[100];
	int res = -1;

	if (!dict || !dict->name)
		return -1;

	sprintf(ifoname, "%s%s%s.%s", soft_conf_dir, SEP, dict->name, IFO_FILE);
	sprintf(idxname, "%s%s%s.%s", soft_conf_dir, SEP, dict->name, IDX_FILE);
	sprintf(dictname, "%s%s%s.%s", soft_conf_dir, SEP, dict->name, DICT_FILE);

	dict->fd_ifo = open(ifoname, OPEN_FILE_MODE_R);
	dict->fd_idx = open(idxname, OPEN_FILE_MODE_R);
	dict->fd_dict = open(dictname, OPEN_FILE_MODE_R);
	if (dict->fd_ifo < 0 || dict->fd_idx < 0 || dict->fd_dict < 0) {
		printf("Open file [%s / %s / %s] err.\n", 
			ifoname, idxname, dictname);
		goto free_fd;
	}

	/* Open file OK */
	res = 0;
	goto ok;

free_fd:
	if (dict->fd_ifo > 0) close(dict->fd_ifo);
	if (dict->fd_idx > 0) close(dict->fd_idx);
	if (dict->fd_dict > 0) close(dict->fd_dict);
ok:
	return res;
}
